package io.gitee.guoguoleo.wrapper;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.lang.func.LambdaUtil;
import cn.hutool.core.util.NumberUtil;
import io.gitee.guoguoleo.enums.SqlLike;
import io.gitee.guoguoleo.model.WhereFieldInfo;
import io.gitee.guoguoleo.utils.FieldUtil;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.update.UpdateSet;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class UpdateWrapper<T> {

    private final Wrapper<T> wrapper;

    public UpdateWrapper() {
        this.wrapper = new Wrapper<>();

        this.wrapper.andFlag = true;
        this.wrapper.orFlag = false;

        this.wrapper.whereExpressionList = new CopyOnWriteArrayList<>();
        this.wrapper.updateSetList = new CopyOnWriteArrayList<>();
    }

    public List<WhereFieldInfo> getWhere(){
        return this.wrapper.whereExpressionList;
    }

    public List<UpdateSet> getUpdate(){
        return this.wrapper.updateSetList;
    }

    /**
     * and操作，不声明默认先使用
     *
     * @return this
     */
    public UpdateWrapper<T> and() {
        this.wrapper.and();
        return this;
    }

    /**
     * or操作，需要声明后使用
     *
     * @return this
     */
    public UpdateWrapper<T> or() {
        this.wrapper.and();
        return this;
    }

    /**
     * eq
     *
     * @param condition 前置条件
     * @param fieldName 字段名称
     * @param value     值
     * @return this
     */
    public UpdateWrapper<T> eq(boolean condition, String fieldName, Object value) {
        this.wrapper.eq(condition, fieldName, value);
        return this;
    }

    /**
     * eq
     *
     * @param fieldName 字段名称
     * @param value     值
     * @return this
     */
    public UpdateWrapper<T> eq(String fieldName, Object value) {
        return this.eq(true, fieldName, value);
    }


    /**
     * eq
     *
     * @param condition 前置条件
     * @param func1     字段名称
     * @param value     值
     * @return this
     */
    public UpdateWrapper<T> eq(boolean condition, Func1<T, ?> func1, Object value) {
        String fieldName = LambdaUtil.getFieldName(func1);
        return this.eq(condition, fieldName, value);
    }

    /**
     * eq
     *
     * @param func1 字段名称
     * @param value 值
     * @return this
     */
    public UpdateWrapper<T> eq(Func1<T, ?> func1, Object value) {
        String fieldName = LambdaUtil.getFieldName(func1);
        return this.eq(true, fieldName, value);
    }

    /**
     * in
     *
     * @param condition 前置条件
     * @param fieldName 名称
     * @param valueList 值列表
     * @return this
     */
    public UpdateWrapper<T> in(boolean condition, String fieldName, Collection<? extends Serializable> valueList) {
        this.wrapper.in(condition, fieldName, valueList);
        return this;
    }

    /**
     * in
     *
     * @param fieldName 名称
     * @return this
     */
    public UpdateWrapper<T> in(String fieldName, Collection<? extends Serializable> valueList) {
        return this.in(true, fieldName, valueList);
    }

    /**
     * in
     *
     * @param condition 前置条件
     * @param fieldName 名称
     * @param values    值列表
     * @return this
     */
    public UpdateWrapper<T> in(boolean condition, String fieldName, Serializable... values) {
        List<Serializable> valueList = ListUtil.toList(values);
        return this.in(condition, fieldName, valueList);
    }

    /**
     * in
     *
     * @param fieldName 名称，支持驼峰或者下划线
     * @return this
     */
    public UpdateWrapper<T> in(String fieldName, Serializable... values) {
        return this.in(true, fieldName, values);
    }


    /**
     * in
     *
     * @param condition 前置条件
     * @param func1     字段
     * @param valueList 值列表
     * @return this
     */
    public UpdateWrapper<T> in(boolean condition, Func1<T, ?> func1, Collection<? extends Serializable> valueList) {
        String fieldName = LambdaUtil.getFieldName(func1);
        return this.in(condition, fieldName, valueList);
    }

    /**
     * in
     *
     * @param func1     字段
     * @param valueList 值列表
     * @return this
     */
    public UpdateWrapper<T> in(Func1<T, ?> func1, Collection<? extends Serializable> valueList) {
        String fieldName = LambdaUtil.getFieldName(func1);
        return this.in(true, fieldName, valueList);
    }

    /**
     * in
     *
     * @param condition 前置条件
     * @param func1     字段
     * @param values    值列表
     * @return this
     */
    public UpdateWrapper<T> in(boolean condition, Func1<T, ?> func1, Serializable... values) {
        String fieldName = LambdaUtil.getFieldName(func1);
        List<Serializable> valueList = ListUtil.toList(values);
        return this.in(condition, fieldName, valueList);
    }

    /**
     * in
     *
     * @param func1  字段
     * @param values 值列表
     * @return this
     */
    public UpdateWrapper<T> in(Func1<T, ?> func1, Serializable... values) {
        String fieldName = LambdaUtil.getFieldName(func1);
        List<Serializable> valueList = ListUtil.toList(values);
        return this.in(true, fieldName, valueList);
    }


    /**
     * like
     *
     * @param condition 前置条件
     * @param fieldName 字段名称
     * @param value     值
     * @param sqlLike   like类型
     * @return this
     */
    public UpdateWrapper<T> like(boolean condition, String fieldName, Object value, SqlLike sqlLike) {
        this.wrapper.like(condition, fieldName, value, sqlLike);
        return this;
    }

    /**
     * like
     *
     * @param condition 前置条件
     * @param fieldName 字段名称
     * @param value     值
     * @return this
     */
    public UpdateWrapper<T> like(boolean condition, String fieldName, Object value) {
        return this.like(condition, fieldName, value, SqlLike.DEFAULT);
    }

    /**
     * like
     *
     * @param fieldName 字段名称
     * @param value     值
     * @return this
     */
    public UpdateWrapper<T> like(String fieldName, Object value) {
        return this.like(true, fieldName, value, SqlLike.DEFAULT);
    }


    /**
     * like
     *
     * @param condition 前置条件
     * @param func1     字段名称
     * @param value     值
     * @param sqlLike   like类型
     * @return this
     */
    public UpdateWrapper<T> like(boolean condition, Func1<T, ?> func1, Object value, SqlLike sqlLike) {
        String fieldName = LambdaUtil.getFieldName(func1);
        return this.like(condition, fieldName, value, sqlLike);
    }

    /**
     * like
     *
     * @param condition 前置条件
     * @param func1     字段名称
     * @param value     值
     * @return this
     */
    public UpdateWrapper<T> like(boolean condition, Func1<T, ?> func1, Object value) {
        String fieldName = LambdaUtil.getFieldName(func1);
        return this.like(condition, fieldName, value, SqlLike.DEFAULT);
    }

    /**
     * like
     *
     * @param func1 字段名称
     * @param value 值
     * @return this
     */
    public UpdateWrapper<T> like(Func1<T, ?> func1, Object value) {
        String fieldName = LambdaUtil.getFieldName(func1);
        return this.like(true, fieldName, value, SqlLike.DEFAULT);
    }


    /**
     * 更新用set字段与值
     *
     * @param condition 前置条件
     * @param fieldName 字段名
     * @param value     值
     * @return this
     */
    public UpdateWrapper<T> set(boolean condition, String fieldName, Object value) {
        this.wrapper.set(condition, fieldName, value);
        return this;
    }

    /**
     * 更新用set字段与值
     *
     * @param fieldName 字段名
     * @param value     值
     * @return this
     */
    public UpdateWrapper<T> set(String fieldName, Object value) {
        return this.set(true, fieldName, value);
    }

    /**
     * 更新用set字段与值
     *
     * @param condition 前置条件
     * @param func1     字段名
     * @param value     值
     * @return this
     */
    public UpdateWrapper<T> set(boolean condition, Func1<T, ?> func1, Object value) {
        String fileName = LambdaUtil.getFieldName(func1);
        return this.set(condition, fileName, value);
    }

    /**
     * 更新用set字段与值
     *
     * @param func1 字段名
     * @param value 值
     * @return this
     */
    public UpdateWrapper<T> set(Func1<T, ?> func1, Object value) {
        String fileName = LambdaUtil.getFieldName(func1);
        return this.set(true, fileName, value);
    }


}
